package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.protobuf.ServiceException;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.leanring.LearningLessonDTO;
import com.tianji.api.dto.leanring.LearningRecordDTO;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.exceptions.DbException;
import com.tianji.common.utils.AssertUtils;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.LearningRecordFormDTO;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.enums.LessonStatus;
import com.tianji.learning.enums.SectionType;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningLessonService;
import com.tianji.learning.service.ILearningRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.List;

import static com.tianji.learning.enums.SectionType.EXAM;

/**
 * <p>
 * 学习记录表 服务实现类
 * </p>
 *
 * @author srj
 * @since 2025-06-28
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LearningRecordServiceImpl extends ServiceImpl<LearningRecordMapper, LearningRecord> implements ILearningRecordService {
    private final ILearningLessonService lessonService;
    private final CourseClient courseClient;

    /**
     *查询指定课程的学习记录
     * @param courseId
     * @return
     */
    @Override
    public LearningLessonDTO queryLearningRecordByCourse(Long courseId) {
        log.info("查询指定课程的学习记录：{}", courseId);
        // 1.获取登录用户
        Long userId = UserContext.getUser();
//         2.查询课表
        LearningLesson lesson = lessonService.lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getCourseId, courseId)
                .one();
//        2.1如果课表不存在，则返回null
        if (ObjectUtils.isEmpty( lesson)){
            return null;
        }
//         3.查询学习记录
//         select * from xx where lesson_id = #{lessonId}
        List<LearningRecord> records = lambdaQuery()
                .eq(LearningRecord::getLessonId, lesson.getId()).list();
        // 4.封装结果
        LearningLessonDTO dto = new LearningLessonDTO();
        dto.setId(lesson.getId());
        dto.setLatestSectionId(lesson.getLatestSectionId());
        dto.setRecords(BeanUtils.copyList(records, LearningRecordDTO.class));
        log.info("查询课表结果：{}", dto);
        return dto;
    }

    @Override
    @Transactional
    public void addLearningRecord(LearningRecordFormDTO recordDTO) {
       //获取当前用户
        Long userId = UserContext.getUser();
        // 2.处理学习记录
        boolean finished = false;
        if(recordDTO.getSectionType() == EXAM){
                finished=handleExamRecord(recordDTO, userId);
        }else {
            finished=handleVideoRecord(recordDTO, userId);
        }
        log.info("处理学习记录结果：{}", finished);
        //3.处理已学习的小节数量
        handleLearningLessonsChanges(recordDTO, finished);
    }

    /**
     * 处理已学习的小节数量
     * @param recordDTO
     * @param userId
     * @return
     */
    private void handleLearningLessonsChanges(LearningRecordFormDTO recordDTO, boolean finished) {
//      查询课表
        log.info("课程是否学完：{}", finished);
        //要加this不然会没有数据？
        LearningLesson lesson  = this.lessonService.getById(recordDTO.getLessonId());
//        if (ObjectUtils.isEmpty(lesson)){
//            throw new BizIllegalException("课程不存在，无法更新数据！");
//        }

        AssertUtils.isNotNull(lesson,"课表信息不存在，无法更新数据");
        // 2.判断是否有新的完成小节
        boolean allLearned = false;
        // 3.判断是否完成
        if (finished){
            // 3.如果有新完成的小节，则需要查询课程数据
            CourseFullInfoDTO courseInfoById = courseClient.getCourseInfoById(lesson.getCourseId(), false, false);
//            if (courseInfoById == null){
//            throw new BizIllegalException("课程不存在，无法更新数据！");
//            }
            AssertUtils.isNotNull(courseInfoById, "课程信息不存在，无法更新数据");
            // 4.比较课程是否全部学完：已学习小节 >= 课程总小节
            allLearned = lesson.getLearnedSections()+1 >= courseInfoById.getSectionNum();
        }
        log.info("课程是否学完：{}", finished);
        // 5.更新课表
        lessonService.lambdaUpdate()
                //更新课程状态
                .set(lesson.getLearnedSections() == 0, LearningLesson::getStatus, LessonStatus.LEARNING.getValue())
                //课程全部学完更新状态
                .set(allLearned, LearningLesson::getStatus, LessonStatus.FINISHED.getValue())
                //更新最近一次学习小节id
                .set(!finished, LearningLesson::getLatestSectionId, recordDTO.getSectionId())
                //更新最近一次学习时间
                .set(!finished, LearningLesson::getLatestLearnTime, recordDTO.getCommitTime())
                //更新已学习小节数量
                .setSql(finished, "learned_sections = learned_sections + 1")
                .eq(LearningLesson::getId, lesson.getId())
                .update();
    }

    /**
     * 处理考试记录
     * @param recordDTO
     * @param userId
     * @return
     */
    private boolean handleExamRecord(LearningRecordFormDTO recordDTO, Long userId) {
        // 1.转换DTO为PO
        LearningRecord learningRecord = BeanUtils.copyBean(recordDTO, LearningRecord.class);
        learningRecord.setUserId(userId);
        learningRecord.setFinished(false);
        learningRecord.setFinishTime(LocalDateTime.now());
        //写入数据库
        boolean save = save(learningRecord);
        if (!save){
            throw new DbException("保存学习记录失败");
        }
        return true;
    }

    /**
     * 处理视频学习记录
     * @param recordDTO
     * @param userId
     * @return
     */
    private boolean handleVideoRecord(LearningRecordFormDTO recordDTO, Long userId) {
        log.info("处理视频学习记录"+recordDTO);
        // 1.查询旧的学习记录
        LearningRecord oldRecord = queryOldRecord(recordDTO.getLessonId(), recordDTO.getSectionId());
        //2.判断是否存在
        if (oldRecord == null) {
            //3.不存在新增
            // 3.1.转换PO
            LearningRecord learningRecord = BeanUtils.copyBean(recordDTO, LearningRecord.class);
            //3.2填充数据
            learningRecord.setUserId(userId);
            //3.3添加数据
            boolean save = save(learningRecord);
            if (!save) {
                throw new DbException("新增学习记录失败");
            }
            return false;
        }
        //4存在的话就修改数据为最新数据
        //4.1判断它是否是第一次学完
        boolean finished  =  !oldRecord.getFinished() && recordDTO.getMoment() << 1 > recordDTO.getDuration();
        log.info("是否完成：{}", finished);
        //4.2更新数据
        boolean update = lambdaUpdate()
                .set(LearningRecord::getMoment, recordDTO.getMoment())
                .set(LearningRecord::getUpdateTime, LocalDateTime.now())
                .set(finished,LearningRecord::getFinished, true)
                .set(finished, LearningRecord::getFinishTime, recordDTO.getCommitTime())
                .eq(LearningRecord::getId, oldRecord.getId())
                .update();
        if(!update){
            throw new DbException("更新学习记录失败！");
        }
        return finished;

    }

    /**
     * 查询旧的学习记录
     * @param lessonId
     * @param sectionId
     * @return
     */
    private LearningRecord queryOldRecord(@NotNull(message = "课表id不能为空") Long lessonId, @NotNull(message = "节的id不能为空") Long sectionId) {
        return lambdaQuery()
                .eq(LearningRecord::getLessonId, lessonId)
                .eq(LearningRecord::getSectionId, sectionId)
                .one();
    }
}
